﻿//========================================================= 
/**@file H002PinPadDevAdapter.h
 * @brief H002标准版密码键盘驱动
 * 
 * @date 2016-07-13   16:44:54
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_H002PINPADDEVADAPTER_H_
#define _LIBZHOUYB_H002PINPADDEVADAPTER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace pinpad {
//--------------------------------------------------------- 
/// 密钥块的大小 
#define H002_KEY_BLOCK_SIZE (8)
/// 拆字的补位数据 
#define H002_EXTEND_BYTE (0x30)
//--------------------------------------------------------- 
/// H002密码键盘部分标准指令集
class H002PinPadDevAdapter :
    public DevAdapterBehavior<IInteractiveTrans>,
    public InterruptBehavior,
    public RefObject
{
public:
    //----------------------------------------------------- 
    /// 算法模式 
    enum AlgorithmMode
    {
        /// 未知的模式 
        UnknownMode = 0,
        /// DES算法 
        DES_Mode,
        /// SM2算法 
        SM2_Mode,
        /// SM4算法 
        SM4_Mode,
        /// RSA算法 
        RSA_Mode
    };
    /// 加解密模式
    enum CryptMode
    {
        UnknownCryptMode = 0x00,
        /* 解密 */
        DES_ECB_DecMode = 0x01,
        DES_CBC_DecMode = 0x02,
        SM4_ECB_DecMode = 0x04,
        SM4_CBC_DecMode = 0x08,
        /* 加密 */
        DES_ECB_EncMode = 0x10,
        DES_CBC_EncMode = 0x20,
        SM4_ECB_EncMode = 0x40,
        SM4_CBC_EncMode = 0x80,
    };
    //----------------------------------------------------- 
    /// 算法模式转描述字符串
    static const char* AlgorithmModeToString(AlgorithmMode mode)
    {
        switch(mode)
        {
        case DES_Mode:
            return "DES";
        case SM2_Mode:
            return "SM2";
        case SM4_Mode:
            return "SM4";
        case RSA_Mode:
            return "RSA";
        default:
            break;
        }
        return "Unknown";
    }
    /// 将算法字符串描述转为枚举
    static AlgorithmMode StringToAlgorithmMode(const char* sMode)
    {
        ByteArray mode(sMode);
        if(StringConvert::Compare(mode, "DES", true))
            return DES_Mode;
        if(StringConvert::Compare(mode, "SM4", true))
            return SM4_Mode;
        if(StringConvert::Compare(mode, "SM2", true))
            return SM2_Mode;
        if(StringConvert::Compare(mode, "RSA", true))
            return RSA_Mode;
        return UnknownMode;
    }
    /// 加解密模式转描述字符串
    static const char* CryptModeToString(CryptMode mode)
    {
        switch(mode)
        {
        case DES_ECB_DecMode:
            return "DES ECB Decrypt";
        case DES_CBC_DecMode:
            return "DES CBC Decrypt";
        case SM4_ECB_DecMode:
            return "SM4 ECB Decrypt";
        case SM4_CBC_DecMode:
            return "SM4 CBC Decrypt";
        case DES_ECB_EncMode:
            return "DES ECB Encrypt";
        case DES_CBC_EncMode:
            return "DES CBC Encrypt";
        case SM4_ECB_EncMode:
            return "SM4 ECB Encrypt";
        case SM4_CBC_EncMode:
            return "SM4 CBC Encrypt";
        default:
            break;
        }
        return "Unknown";
    }
    //----------------------------------------------------- 
protected:
    //----------------------------------------------------- 
    /// 发送缓冲区 
    ByteBuilder _sendBuffer;
    /// 接收缓冲区 
    ByteBuilder _recvBuffer;
    /// 转换密钥字节
    inline byte _KeyByte(byte data)
    {
        if(data == 0xFF)
            return data;
        return (data & 0x0F) | H002_EXTEND_BYTE;
    }
    /// 转换密钥字节
    inline byte _KeyByte(size_t data)
    {
        return _itobyte((data & 0x0F) | H002_EXTEND_BYTE);
    }
    /// 转换密钥类型
    inline byte _KeyUse(AlgorithmMode mode)
    {
        return (mode == SM4_Mode) ? 0x31 : 0x30;
    }
    /// 是否语音提示再次输入
    inline byte _Voice(bool isReVoice)
    {
        return isReVoice ? 0x31 : 0x30;
    }
    /// 是否需要按确认键返回
    inline byte _Enter(bool isEnter)
    {
        return isEnter ? 0x31 : 0x30;
    }
    /// 截取KCV
    inline ByteArray _KeyKCV(AlgorithmMode mode, const ByteArray& kcv)
    {
        size_t len = (mode == SM4_Mode) ? 8 : 4;
        return kcv.SubArray(0, len);
    }
    //----------------------------------------------------- 
    /**
     * @brief 主密钥加解密数据
     * @date 2016-11-15 21:47
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] mode 加解密模式
     * @param [in] iv_8_16 IV(DES:8, SM4:16)
     * @param [in] buff_8_16 待加密数据(DES:8,SM4:16)
     * @param [out] data_8_16 加密后的数据
     */
    bool _MKeyCrypt(byte mkIndex, CryptMode mode, const ByteArray& iv_8_16, const ByteArray& buff_8_16, ByteBuilder& data_8_16)
    {
        LOGGER(_log << "MkIndex:<" << _hex_num(mkIndex) << ">\n"
            << "Mode:<" << CryptModeToString(mode) << " (" << _hex_num(mode, sizeof(byte)) << ")>\n";
        _log << "IV:<";_log.WriteStream(iv_8_16) << ">\n";
        _log << "Buff:" << buff_8_16 << endl);
        ASSERT_FuncErr(this->IsValid(), DeviceError::DevInvalidErr);

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1b h m", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += static_cast<byte>(mode);
        ByteConvert::Expand(iv_8_16, _sendBuffer, H002_EXTEND_BYTE);
        ByteConvert::Expand(buff_8_16, _sendBuffer, H002_EXTEND_BYTE);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        ASSERT_FuncErr(_recvBuffer.GetLength() > 0, DeviceError::RecvFormatErr);
        size_t len = _recvBuffer[0];
        data_8_16 += _recvBuffer.SubArray(1, len);
        LOGGER(_log << "DATA:<";
        _log.WriteStream(_recvBuffer.SubArray(1, len)) << ">\n");

        return true;
    }
    /**
     * @brief 工作密钥加解密数据
     * @date 2016-11-16 13:50
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引
     * @param [in] mode 加解密模式
     * @param [in] iv_8_16 IV(DES:8,SM4:16)
     * @param [in] buff_8_16 待加解密的数据(DES:8,SM4:16)
     * @param [out] data_8_16 加解密后的数据(DES:8,SM4:16)
     */
    bool _WKeyCrypt(byte mkIndex, byte wkIndex, CryptMode mode, const ByteArray& iv_8_16, const ByteArray& buff_8_16, ByteBuilder& data_8_16)
    {
        LOGGER(_log << "MkIndex:<" << _hex_num(mkIndex) << ">\n"
            << "WkIndex:<" << _hex_num(wkIndex) << ">\n"
            << "Mode:<" << CryptModeToString(mode) << " (" << _hex_num(mode, sizeof(byte)) << ")>\n";
        _log << "IV:<";_log.WriteStream(iv_8_16) << ">\n";
        _log << "Buff:" << buff_8_16 << endl);
        ASSERT_FuncErr(this->IsValid(), DeviceError::DevInvalidErr);

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B h u", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += static_cast<byte>(mode);
        ByteConvert::Expand(iv_8_16, _sendBuffer, H002_EXTEND_BYTE);
        ByteConvert::Expand(buff_8_16, _sendBuffer, H002_EXTEND_BYTE);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        ASSERT_FuncErr(_recvBuffer.GetLength() > 0, DeviceError::RecvFormatErr);
        size_t len = _recvBuffer[0];
        data_8_16 += _recvBuffer.SubArray(1, len);
        LOGGER(_log << "DATA:<";
        _log.WriteStream(_recvBuffer.SubArray(1, len)) << ">\n");
        return true;
    }
    //----------------------------------------------------- 
public:
    //----------------------------------------------------- 
    /// 蜂鸣器控制
    bool Beep()
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte beepCmd[2] = { 0x1B, 'b' };
        return _logRetValue(_pDev->Write(ByteArray(beepCmd, 2)));
    }
    /**
     * @brief 写设备序列号
     * @date 2016-07-14 15:45
     * 
     * @param [in] serialNumber 需要写入的序列号
     */
    bool SetSerialNumber(const ByteArray& serialNumber)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "序列号:<";
        _log.WriteStream(serialNumber) << ">\n");
        ASSERT_Device();
        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B W SN", _sendBuffer);
        _sendBuffer += serialNumber;
        DevCommand::FromAscii("0D 0A", _sendBuffer);
        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        return _logRetValue(true);
    }
    /**
     * @brief 读设备序列号
     * @date 2016-07-14 15:45
     * 
     * @param [out] serialNumber 获取到的设备序列号
     */
    bool GetSerialNumber(ByteBuilder& serialNumber)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B W 0D 0A", _sendBuffer);
        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        LOGGER(_log << "序列号:<";
        _log.WriteStream(_recvBuffer) << ">");
        serialNumber += _recvBuffer;

        return _logRetValue(true);
    }
    /**
     * @brief 写应用区编号
     * @date 2016-07-14 17:17
     * 
     * @param [in] id_M32 需要写入的应用区编号(最大32字节)
     */
    bool SetAppID(const ByteArray& id_M32)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "应用编号:";
        _log.WriteStream(id_M32) << endl);
        ASSERT_Device();
        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B s w", _sendBuffer);
        ByteConvert::Expand(id_M32.SubArray(0, 32), _sendBuffer, H002_EXTEND_BYTE);
        DevCommand::FromAscii("0D 0A", _sendBuffer);

        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        return _logRetValue(true);
    }
    /**
     * @brief 获取应用区编号
     * @date 2016-07-14 17:18
     * 
     * @param [out] id 获取到的应用区编号
     */
    bool GetAppID(ByteBuilder& id)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B s r 0D 0A", _sendBuffer);
        ASSERT_FuncErr(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErr(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        LOGGER(_log << "应用编号:<";
        _log.WriteStream(_recvBuffer) << ">\n");

        id += _recvBuffer;
        return _logRetValue(true);
    }
    /**
     * @brief 重置主密钥(默认重置所有密钥)
     * @date 2016-07-15 10:49
     * 
     * @param [in] mkIndex 需要重置的密钥索引,重置后密钥值为:0x40 + MkIndex
     */
    bool ResetMK(byte mkIndex = 'A')
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "密钥索引:<" << _hex_num(mkIndex) << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B 64", _sendBuffer);
        if(mkIndex == 'A')
        {
            _sendBuffer += mkIndex;
        }
        else
        {
            _sendBuffer += _KeyByte(mkIndex);
        }
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        return _logRetValue(true);
    }
    /**
     * @brief 明文更新主密钥
     * @date 2016-07-15 11:28
     * 
     * @param [in] keyIndex 需要更新的主密钥索引
     * @param [in] oldMKey_8_16_24 需要更新的旧主密钥值
     * @param [in] newMKey_8_16_24 需要更新的新主密钥值
     * @param [in] newMKeyMode 新主密钥的类型(DES/SM4)
     */
    bool UpdateMainKey(byte keyIndex, const ByteArray& oldMKey_8_16_24, const ByteArray& newMKey_8_16_24, AlgorithmMode newMKeyMode)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(keyIndex) << ">\n";
        _log << "旧主密钥:<";_log.WriteStream(oldMKey_8_16_24) << ">\n";
        _log << "新主密钥:<";_log.WriteStream(newMKey_8_16_24) << ">\n";
        _log << "新主密钥类型:<" << newMKeyMode << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B kM", _sendBuffer);
        _sendBuffer += _KeyByte(keyIndex);
        _sendBuffer += _KeyByte(oldMKey_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(oldMKey_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyByte(newMKey_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(newMKey_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyUse(newMKeyMode);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        return _logRetValue(true);
    }
    /**
     * @brief 明文更新主密钥,返回KCV
     * @date 2016-07-15 13:43
     * 
     * @param [in] keyIndex 需要更新的主密钥索引
     * @param [in] oldMKey_8_16_24 需要更新的旧主密钥值
     * @param [in] newMKey_8_16_24 需要更新的新主密钥值
     * @param [in] newMKeyMode 新主密钥的类型(DES/SM4)
     * @param [out] pKCV_16 [default:NULL] 设备返回的KCV
     */
    bool UpdateMainKey_KCV(byte keyIndex, const ByteArray& oldMKey_8_16_24, const ByteArray& newMKey_8_16_24, AlgorithmMode newMKeyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(keyIndex) << ">\n";
        _log << "旧主密钥:<";_log.WriteStream(oldMKey_8_16_24) << ">\n";
        _log << "新主密钥:<";_log.WriteStream(newMKey_8_16_24) << ">\n";
        _log << "新主密钥类型:<" << newMKeyMode << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B kN", _sendBuffer);
        _sendBuffer += _KeyByte(keyIndex);
        _sendBuffer += _KeyByte(oldMKey_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(oldMKey_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyByte(newMKey_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(newMKey_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyUse(newMKeyMode);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        LOGGER(_log << "KCV:<";_log.WriteStream(_recvBuffer) << ">\n");
        if(pKCV_16 != NULL)
        {
            pKCV_16->Append(_recvBuffer);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 密文下载主密钥
     * @date 2016-07-15 14:22
     * 
     * @param [in] keyIndex 需要下载的主密钥索引
     * @param [in] encryptedMK_8_16_24 主密钥密文
     * @param [in] kcv_4_8 KCV(内部支持自动截取长度)
     * @param [in] keyMode 密钥算法用途(DES/SM4)
     * @param [out] pKCV_16 [default:NULL] 设备返回的KCV
     */
    bool UpdateEncryptedMainKey(byte mkIndex, const ByteArray& encryptedMK_8_16_24, const ByteArray& kcv_4_8, AlgorithmMode keyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "密钥密文:<";_log.WriteStream(encryptedMK_8_16_24) << ">\n";
        _log << "KCV:<";_log.WriteStream(kcv_4_8) << ">\n";
        _log << "主密钥类型:<" << keyMode << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();
        if(pKCV_16 == NULL)
        {
            DevCommand::FromFormat("1B km", _sendBuffer);
        }
        else
        {
            DevCommand::FromFormat("1B kn", _sendBuffer);
        }
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(encryptedMK_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(encryptedMK_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        ByteConvert::Expand(_KeyKCV(keyMode, kcv_4_8), _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyUse(keyMode);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        if(pKCV_16 != NULL)
        {
            LOGGER(_log << "KCV:<";_log.WriteStream(_recvBuffer) << ">\n");
            pKCV_16->Append(_recvBuffer);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 不带校验密文修改主密钥,返回KCV
     * @date 2016-07-15 14:28
     * 
     * @param [in] mkIndex 需要下载的主密钥索引
     * @param [in] encryptedMK_8_16_24 主密钥密文
     * @param [in] keyMode 密钥算法用途(DES/SM4)
     * @param [out] pKCV_16 [default:NULL] 设备返回的KCV
     */
    bool UpdateEncryptedMainKey(byte mkIndex, const ByteArray& encryptedMK_8_16_24, AlgorithmMode keyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "密钥密文:<";_log.WriteStream(encryptedMK_8_16_24) << ">\n";
        _log << "主密钥类型:<" << keyMode << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B ko", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(encryptedMK_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(encryptedMK_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyUse(keyMode);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        LOGGER(_log << "KCV:<";_log.WriteStream(_recvBuffer) << ">\n");
        if(pKCV_16 != NULL)
        {
            pKCV_16->Append(_recvBuffer);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 密文修改工作密钥
     * @date 2016-07-15 15:02
     * 
     * @param [in] mkIndex 加密的主密钥索引
     * @param [in] wkIndex 需要更新的工作密钥索引
     * @param [in] encryptedWK_8_16_24 工作密钥密文
     * @param [in] kcv_4_8 KCV(内部支持自动截取长度)
     * @param [in] keyMode 密钥算法用途(DES/SM4)
     * @param [out] pKCV_16 [default:NULL] 设备返回的KCV
     */
    bool UpdateEncryptedWorkKey(byte mkIndex, byte wkIndex, const ByteArray& encryptedWK_8_16_24, const ByteArray& kcv_4_8, AlgorithmMode keyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n";
        _log << "工作密钥密文:<";_log.WriteStream(encryptedWK_8_16_24) << ">\n";
        _log << "KCV:<";_log.WriteStream(kcv_4_8) << ">\n";
        _log<<"算法用途:<"<<keyMode<<">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        if(pKCV_16 == NULL)
        {
            DevCommand::FromFormat("1B ku", _sendBuffer);
        }
        else
        {
            DevCommand::FromFormat("1B kv", _sendBuffer);
        }
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += _KeyByte(encryptedWK_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(encryptedWK_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        ByteConvert::Expand(_KeyKCV(keyMode, kcv_4_8), _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyByte(static_cast<byte>(keyMode));
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        if(pKCV_16 != NULL)
        {
            LOGGER(_log << "KCV:<";_log.WriteStream(_recvBuffer) << ">\n");
            pKCV_16->Append(_recvBuffer);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 密文修改工作密钥,不带校验返回KCV
     * @date 2016-07-15 15:31
     * 
     * @param [in] mkIndex 加密的主密钥索引
     * @param [in] wkIndex 需要更新的工作密钥索引
     * @param [in] encryptedWK_8_16_24 工作密钥密文
     * @param [in] keyMode 密钥算法用途(DES/SM4)
     * @param [out] pKCV_16 [default:NULL] 设备返回的KCV
     */
    bool UpdateEncryptedWorkKey(byte mkIndex, byte wkIndex, const ByteArray& encryptedWK_8_16_24, AlgorithmMode keyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n";
        _log << "工作密钥密文:<";_log.WriteStream(encryptedWK_8_16_24) << ">\n";
        _log << "算法用途:<" << keyMode << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B kw", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += _KeyByte(encryptedWK_8_16_24.GetLength() / H002_KEY_BLOCK_SIZE);
        ByteConvert::Expand(encryptedWK_8_16_24, _sendBuffer, H002_EXTEND_BYTE);
        _sendBuffer += _KeyUse(keyMode);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        if(pKCV_16 != NULL)
        {
            LOGGER(_log << "KCV:<";_log.WriteStream(_recvBuffer) << ">\n");
            pKCV_16->Append(_recvBuffer);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 密文输入密码
     * @date 2016-07-15 15:45
     * 
     * @param [in] mkIndex 主密钥号
     * @param [in] wkIndex 工作密钥号
     * @param [in] pwdlen 期望输入的长度
     * @param [in] isReVoice 语音,是否再次输入
     * @param [in] isEnter 是否需要按确认键后返回
     * @param [in] isClearAll 按退格时是否清除全部按键
     * @param [in] isDisableEnter 是否允许到最大长度时才能按回车
     * @param [out] pin 输入的密文密码
     * @param [out] pinLen 实际输入的密码长度
     */
    bool InputPassword(byte mkIndex, byte wkIndex, size_t pwdlen, 
        bool isReVoice, bool isEnter, bool isClearAll, bool isDisableEnter, 
        ByteBuilder& pin, size_t& pinLen)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n";
        _log << "期望输入的长度:<" << pwdlen << ">\n";
        _log << "是否为再次输入语音:<" << isReVoice << ">\n";
        _log << "是否需要确认键返回:<" << isEnter << ">\n";
        _log << "退格是否全部清除:<" << isClearAll << ">\n";
        _log << "是否到最大长度才允许按回车:<" << isDisableEnter << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B ip", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += _Voice(isReVoice);
        _sendBuffer += _Enter(isEnter);
        _sendBuffer += _KeyByte((pwdlen & 0xF0) >> HALF_BIT_OFFSET);
        _sendBuffer += _KeyByte(pwdlen);
        _sendBuffer += _Enter(isClearAll);
        _sendBuffer += _Enter(isDisableEnter);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        ASSERT_FuncErrRet(_recvBuffer.GetLength() > 1, DeviceError::RecvFormatErr);
        LOGGER(_log << "密文密码:<";_log.WriteStream(_recvBuffer) << ">\n");
        pinLen = _recvBuffer[0];
        pin += _recvBuffer.SubArray(1);
        return _logRetValue(true);
    }
    /**
     * @brief 加密输入密码,按键返回*号(数据通过GetPassword获取)
     * @warning 与GetPassword配对使用
     * @date 2016-07-15 16:18
     * 
     * @param [in] pwdlen 期望输入的密码长度
     * @param [in] isReVoice 语音,是否再次输入
     * @param [in] isEnter 是否需要按确认键后返回
     * @param [in] isClearAll 按退格时是否清除全部按键
     * @param [in] isDisableEnter 是否允许到最大长度时才能按回车
     */
    bool WaitPassword(size_t pwdlen, bool isReVoice, bool isEnter, bool isClearAll, bool isDisableEnter)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "期望输入的长度:<" << pwdlen << ">\n";
        _log << "是否为再次输入语音:<" << isReVoice << ">\n";
        _log << "是否需要确认键返回:<" << isEnter << ">\n";
        _log << "退格是否全部清除:<" << isClearAll << ">\n";
        _log << "是否到最大长度才允许按回车:<" << isDisableEnter << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B iq", _sendBuffer);
        _sendBuffer += _Voice(isReVoice);
        _sendBuffer += _Enter(isEnter);
		_sendBuffer += _KeyByte((pwdlen & 0xF0) >> HALF_BIT_OFFSET);
        _sendBuffer += _KeyByte(pwdlen);
        _sendBuffer += _Enter(isClearAll);
        _sendBuffer += _Enter(isDisableEnter);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        return _logRetValue(true);
    }
    /**
     * @brief 获取密文
     * @warning 需要在WaitPassword配对使用
     * @date 2016-07-18 15:09
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引
     * @param [out] pin 获取到的密文密钥
     * @param [out] pinLen 获取到的密码长度
     */
    bool GetPassword(byte mkIndex, byte wkIndex, ByteBuilder& pin, size_t& pinLen)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B )", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        LOGGER(_log << "密文密码:<";_log.WriteStream(_recvBuffer) << ">\n");
        pinLen = _recvBuffer[0];
        pin += _recvBuffer.SubArray(1);
        return _logRetValue(true);
    }
    /**
     * @brief 获取PINBLOCK
     * @date 2016-07-19 11:16
     * 
     * @param [in] accno_12 用户12位主帐号
     * @param [in] mkIndex 加密的主密钥索引
     * @param [in] wkIndex 加密的工作密钥索引
     * @param [in] pwdlen 期望输入的密码长度
     * @param [in] isReVoice 是否提示再次输入
     * @param [in] isEnter 是否需要按确认键才返回
     * @param [in] isClearAll 按退格时是否清除全部按键
     * @param [in] isDisableEnter 是否允许到最大长度时才能按回车
     *
     * @param [out] pinblock 获取到的pinblock
     */
    bool InputPinblock(const ByteArray& accno_12, byte mkIndex, byte wkIndex, size_t pwdlen, 
        bool isReVoice, bool isEnter, bool isClearAll, bool isDisableEnter,
        ByteBuilder& pinblock)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "帐号:<"; _log.WriteStream(accno_12) << ">\n";
        _log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n";
        _log << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n";
        _log << "期望密码长度:<" << pwdlen << ">\n";
        _log << "是否提示再次输入:<" << isReVoice << ">\n";
        _log << "是否需要按确认键:<" << isEnter << ">\n";
        _log << "退格是否全部清除:<" << isClearAll << ">\n";
        _log << "是否到最大长度才允许按回车:<" << isDisableEnter << ">\n");
        ASSERT_Device();
        ASSERT_FuncErrInfoRet(accno_12.GetLength() == 12, DeviceError::ArgLengthErr, "帐号长度错误");

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B ic", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += _Voice(isReVoice);
        _sendBuffer += accno_12;
        _sendBuffer += _Enter(isEnter);
		_sendBuffer += _KeyByte((pwdlen & 0xF0) >> HALF_BIT_OFFSET);
        _sendBuffer += _KeyByte(pwdlen);
        _sendBuffer += _Enter(isClearAll);
        _sendBuffer += _Enter(isDisableEnter);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::RecvErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        size_t len = _recvBuffer[0];
        pinblock += _recvBuffer.SubArray(1, len);
        LOGGER(_log << "Pinblock:<";
        _log.WriteStream(_recvBuffer.SubArray(1, len)) << ">\n");
        return _logRetValue(true);
    }
    /**
     * @brief 带*号返回PINBLOCK输入(数据通过GetPinblock获取)
     * @date 2016-11-15 22:19
     * 
     * @param [in] pwdlen 期望输入的密码长度
     * @param [in] isReVoice 是否提示再次输入
     * @param [in] isEnter 是否需要按确认键才返回
     * @param [in] isClearAll 按退格时是否清除全部按键
     * @param [in] isDisableEnter 是否允许到最大长度时才能按回车
     */
    bool WaitPinblock(size_t pwdlen, bool isReVoice, bool isEnter, bool isClearAll, bool isDisableEnter)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "期望密码长度:<" << pwdlen << ">\n";
        _log << "是否提示再次输入:<" << isReVoice << ">\n";
        _log << "是否需要按确认键:<" << isEnter << ">\n";
        _log << "退格是否全部清除:<" << isClearAll << ">\n";
        _log << "是否到最大长度才允许按回车:<" << isDisableEnter << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B id", _sendBuffer);
        _sendBuffer += _Voice(isReVoice);
        _sendBuffer += _Enter(isEnter);
        _sendBuffer += _KeyByte((pwdlen & 0xF0) >> HALF_BIT_OFFSET);
        _sendBuffer += _KeyByte(pwdlen);
        _sendBuffer += _Enter(isClearAll);
        _sendBuffer += _Enter(isDisableEnter);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        return _logRetValue(true);
    }
    /**
     * @brief 获取帐号的PINBLOCK
     * @date 2016-11-15 22:33
     * 
     * @param [in] mkIndex 加密数据的主密钥号
     * @param [in] wkIndex 加密数据的工作密钥号
     * @param [in] accno_12 加密主帐号
     * @param [out] pin 加密后的数据
     * @param [out] pPinLen [default:NULL] 加密密钥的长度
     */
    bool GetPinblock(byte mkIndex, byte wkIndex, const ByteArray& accno_12, ByteBuilder& pin, size_t* pPinLen = NULL)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "主密钥索引:<" << _hex_num(mkIndex) << ">\n"
            << "工作密钥索引:<" << _hex_num(wkIndex) << ">\n"
            << "主帐号:<";
        _log.WriteStream(accno_12) << ">\n");
        ASSERT_Device();
        ASSERT_FuncErrInfoRet(accno_12.GetLength() == 12, DeviceError::ArgFormatErr, "帐号长度错误");

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B (", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        _sendBuffer += accno_12;
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        ASSERT_FuncErrRet(_recvBuffer.GetLength() > 0, DeviceError::RecvFormatErr);
        if(pPinLen != NULL)
        {
            (*pPinLen) = _recvBuffer[0];
            LOGGER(_log << "PinLength:<" << static_cast<int>(_recvBuffer[0]));
        }
        pin += _recvBuffer.SubArray(1);
        LOGGER(_log << "Pinblock:<";
        _log.WriteStream(_recvBuffer.SubArray(1)) << ">\n");
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥加解密数据
     * @date 2016-11-15 21:47
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] mode 加解密模式
     * @param [in] iv_8_16 IV(DES:8, SM4:16)
     * @param [in] buff_8_16 待加密数据(DES:8,SM4:16)
     * @param [out] data_8_16 加密后的数据
     */
    bool MKeyCrypt(byte mkIndex, CryptMode mode, const ByteArray& iv_8_16, const ByteArray& buff_8_16, ByteBuilder& data_8_16)
    {
        LOG_FUNC_NAME();
        return _logRetValue(_MKeyCrypt(mkIndex, mode, iv_8_16, buff_8_16, data_8_16));
    }
    /**
     * @brief 工作密钥加解密数据
     * @date 2016-11-16 13:50
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引
     * @param [in] mode 加解密模式
     * @param [in] iv_8_16 IV(DES:8,SM4:16)
     * @param [in] buff_8_16 待加解密的数据(DES:8,SM4:16)
     * @param [out] data_8_16 加解密后的数据(DES:8,SM4:16)
     */
    bool WKeyCrypt(byte mkIndex, byte wkIndex, CryptMode mode,
        const ByteArray& iv_8_16, const ByteArray& buff_8_16,
        ByteBuilder& data_8_16)
    {
        LOG_FUNC_NAME();
        return _logRetValue(_WKeyCrypt(mkIndex, wkIndex, mode, iv_8_16, buff_8_16, data_8_16));
    }
    /**
     * @brief 计算MAC
     * @date 2016-11-16 15:45
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引(FF时使用主密钥计算)
     * @param [in] iv_16 IV(DES和SM4都统一传16个字节的IV,固件自动截取)
     * @param [in] buff_8_16 计算MAC的数据源(DES:8,SM4:16)
     * @param [out] mac_8_16 MAC(DES:8,SM4:16)
     * @param [out] pPinLen [default:NULL] 计算MAC的密钥长度
     */
    bool GetMAC(byte mkIndex, byte wkIndex, const ByteArray& iv_16,
        const ByteArray& buff_8_16, ByteBuilder& mac_8_16, size_t* pKeyKen = NULL)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        LOGGER(_log << "MkIndex:<" << _hex_num(mkIndex) << ">\n"
            << "WkIndex:<" << _hex_num(wkIndex) << ">\n";
        _log << "IV:<";_log.WriteStream(iv_16) << ">\n";
        _log << "Buff:" << buff_8_16 << endl);

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B h c", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        ByteConvert::Expand(iv_16, _sendBuffer, H002_EXTEND_BYTE);
        ByteConvert::Expand(buff_8_16, _sendBuffer, H002_EXTEND_BYTE);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        ASSERT_FuncErrRet(_recvBuffer.GetLength() > 1, DeviceError::RecvFormatErr);
        size_t len = _recvBuffer[0];
        if(pKeyKen != NULL)
        {
            *pKeyKen = len;
        }
        LOGGER(_log << "KeyLength:<" << len << ">\n");
        mac_8_16 += _recvBuffer.SubArray(1);
        LOGGER(_log << "MAC:<";
        _log.WriteStream(_recvBuffer) << ">\n");

        return _logRetValue(true);
    }
    /**
     * @brief 取指定密钥的KCV
     * @date 2016-11-16 16:24
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引(FF时使用主密钥计算)
     * @param [out] kcv 密钥的KCV
     */
    bool GetKCV(byte mkIndex, byte wkIndex, ByteBuilder& kcv)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        LOGGER(_log << "MkIndex:<" << _hex_num(mkIndex) << ">\n"
            << "WkIndex:<" << _hex_num(wkIndex) << ">\n");

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B kc", _sendBuffer);
        _sendBuffer += _KeyByte(mkIndex);
        _sendBuffer += _KeyByte(wkIndex);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);
        kcv += _recvBuffer;
        LOGGER(_log << "KCV:<";
        _log.WriteStream(_recvBuffer) << ">\n");

        return _logRetValue(true);
    }
    /**
     * @brief 明文输入
     * @date 2016-11-16 19:38
     * 
     * @param [in] isEnter 是否需要按确认键返回
     * @param [in] pinlen 期望输入的密码长度
     * @param [in] isClearAll 按退格时是否清除全部按键
     * @param [in] isDisableEnter 是否允许到最大长度时才能按回车
     * @param [out] input 输入的明文数据
     */
    bool Input(bool isEnter, size_t pinlen, bool isClearAll, bool isDisableEnter, ByteBuilder& input)
    {
        LOG_FUNC_NAME();
        LOGGER(_log << "是否提示再次输入:<" << isEnter << ">\n"
            << "期望输入长度:<" << pinlen << ">\n";
        _log << "退格是否全部清除:<" << isClearAll << ">\n";
        _log << "是否到最大长度才允许按回车:<" << isDisableEnter << ">\n");
        ASSERT_Device();

        _sendBuffer.Clear();
        _recvBuffer.Clear();

        DevCommand::FromFormat("1B I", _sendBuffer);
        _sendBuffer += _Enter(isEnter);
        _sendBuffer += _KeyByte((pinlen & 0xF0) >> HALF_BIT_OFFSET);
        _sendBuffer += _KeyByte(pinlen);
        _sendBuffer += _Enter(isClearAll);
        _sendBuffer += _Enter(isDisableEnter);
        DevCommand::FromFormat("0D 0A", _sendBuffer);

        ASSERT_FuncErrRet(_pDev->Write(_sendBuffer), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        LOGGER(_log << "Input:<";_log.WriteStream(_recvBuffer) << ">\n");
        input += _recvBuffer;

        return _logRetValue(true);
    }
    /// 开始明文输入(数据通过GetInput获取)
    bool WaitInput(bool isReVoice)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte inputCmd[1] = { 0 };
        inputCmd[0] = isReVoice ? 0x82 : 0x81;
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(inputCmd, 1)), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /// 取消输入
    bool CancelInput()
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte inputCmd[1] = { 0x83 };
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(inputCmd, 1)), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /// 关闭密码键盘
    bool Reset()
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        byte resetCmd[2] = { 0x1B, 0x30 };
        ASSERT_FuncErrRet(_pDev->Write(ByteArray(resetCmd, 2)), DeviceError::SendErr);
        return _logRetValue(true);
    }
    /// 获取版本
    bool GetVersion(ByteBuilder& version)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        
        byte verCmd[2] = { 0x1B, 'V' };

        _recvBuffer.Clear();

        ASSERT_FuncErrRet(_pDev->Write(ByteArray(verCmd, 2)), DeviceError::SendErr);
        ASSERT_FuncErrRet(_pDev->Read(_recvBuffer), DeviceError::RecvErr);

        LOGGER(_log << "Version:<";_log.WriteStream(_recvBuffer) << ">\n");
        version += _recvBuffer;

        return _logRetValue(true);
    }
    //----------------------------------------------------- 
    /* 二次封装后的函数 */
    /// 初始化主密钥为固定值
    bool ResetMK(byte mkIndex, const ByteArray& mk_8_16_24, AlgorithmMode keyMode)
    {
        LOG_FUNC_NAME();
        if(!ResetMK(mkIndex))
        {
            return _logRetValue(false);
        }
        ByteBuilder oldMk(16);
        oldMk.Append(0x40 + mkIndex, 16);
        if(!UpdateMainKey(mkIndex, oldMk, mk_8_16_24, keyMode))
        {
            return _logRetValue(false);
        }
        return _logRetValue(true);
    }
    /**
     * @brief 明文下载工作密钥
     * @date 2016-11-17 16:20
     * 
     * @param [in] mkIndex 主密钥索引
     * @param [in] wkIndex 工作密钥索引
     * @param [in] wk_8_16_24 工作密钥明文
     * @param [in] keyMode 密钥模式
     * @param [out] pKCV_16 [default:NULL] 工作密钥KCV
     */
    bool UpdateWorkKey(byte mkIndex, byte wkIndex, const ByteArray& wk_8_16_24, 
        AlgorithmMode keyMode, ByteBuilder* pKCV_16 = NULL)
    {
        LOG_FUNC_NAME();
        byte iv[16] = { 0 };
        size_t ivlen = (keyMode == SM4_Mode) ? 16 : 8;
        CryptMode mode = (keyMode == SM4_Mode) ? SM4_ECB_EncMode : DES_ECB_EncMode;

        ByteBuilder wkEncVal(16);
        if(!MKeyCrypt(mkIndex, mode, ByteArray(iv, ivlen), wk_8_16_24, wkEncVal))
        {
            LOGGER(_log.WriteLine("获取工作密钥密文失败"));
            return _logRetValue(false);
        }
        LOGGER(_log << "工作密钥密文:<" << _hex(wkEncVal) << ">\n");
        if(!UpdateEncryptedWorkKey(mkIndex, wkIndex, wk_8_16_24, keyMode, pKCV_16))
        {
            LOGGER(_log.WriteLine("下载工作密钥失败"));
            return _logRetValue(false);
        }
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
    /**
     * @brief 主密钥DES ECB加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] data_8X 待加密的数据
     * @param [out] buff_8X 加密后的数据
     */
    bool MK_DES_ECB_Encrypt(byte mkIndex, const ByteArray& data_8X, ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_ECB_EncMode;
        size_t ivlen = 8;
        byte iv[8] = { 0 };

        ASSERT_FuncErrRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, ByteArray(iv, ivlen),
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥SM4 ECB加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] data_16X 待加密的数据
     * @param [out] buff_16X 加密后的数据
     */
    bool MK_SM4_ECB_Encrypt(byte mkIndex, const ByteArray& data_16X, ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_ECB_EncMode;
        size_t ivlen = 16;
        byte iv[16] = { 0 };

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, ByteArray(iv, ivlen),
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥DES CBC加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] iv_8 向量
     * @param [in] data_8X 待加密的数据
     * @param [out] buff_8X 加密后的数据
     */
    bool MK_DES_CBC_Encrypt(byte mkIndex, const ByteArray& iv_8, const ByteArray& data_8X, ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_CBC_EncMode;
        size_t ivlen = 8;

        ASSERT_FuncErrInfoRet(iv_8.GetLength() >= ivlen, DeviceError::ArgLengthErr,
            "IV长度错误");
        ASSERT_FuncErrInfoRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr, "待加密数据长度错误");

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, iv_8,
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥SM4 CBC加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] iv_16 向量
     * @param [in] data_16X 待加密的数据
     * @param [out] buff_16X 加密后的数据
     */
    bool MK_SM4_CBC_Encrypt(byte mkIndex, const ByteArray& iv_16, const ByteArray& data_16X, ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_CBC_EncMode;
        size_t ivlen = 16;

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, iv_16,
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
    /**
     * @brief 主密钥DES ECB解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] data_8X 待解密的数据
     * @param [out] buff_8X 解密后的数据
     */
    bool MK_DES_ECB_Decrypt(byte mkIndex, const ByteArray& data_8X, ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_ECB_DecMode;
        size_t ivlen = 8;
        byte iv[8] = { 0 };

        ASSERT_FuncErrRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, ByteArray(iv, ivlen),
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥SM4 ECB解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] data_16X 待解密的数据
     * @param [out] buff_16X 解密后的数据
     */
    bool MK_SM4_ECB_Decrypt(byte mkIndex, const ByteArray& data_16X, ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_ECB_DecMode;
        size_t ivlen = 16;
        byte iv[16] = { 0 };

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, ByteArray(iv, ivlen),
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥DES CBC解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] iv_8 向量
     * @param [in] data_8X 待解密的数据
     * @param [out] buff_8X 解密后的数据
     */
    bool MK_DES_CBC_Decrypt(byte mkIndex, const ByteArray& iv_8, const ByteArray& data_8X, ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_CBC_DecMode;
        size_t ivlen = 8;

        ASSERT_FuncErrInfoRet(iv_8.GetLength() >= ivlen, DeviceError::ArgLengthErr,
            "IV长度错误");
        ASSERT_FuncErrInfoRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr, "待解密数据长度错误");

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, iv_8,
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 主密钥SM4 CBC解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] iv_16 向量
     * @param [in] data_16X 待解密的数据
     * @param [out] buff_16X 解密后的数据
     */
    bool MK_SM4_CBC_Decrypt(byte mkIndex, const ByteArray& iv_16, const ByteArray& data_16X, ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_CBC_DecMode;
        size_t ivlen = 16;

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_MKeyCrypt(mkIndex, mode, iv_16,
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
    /**
     * @brief 工作密钥DES ECB加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] wkIndex 加密数据的工作密钥索引
     * @param [in] data_8X 待加密的数据
     * @param [out] buff_8X 加密后的数据
     */
    bool WK_DES_ECB_Encrypt(byte mkIndex, byte wkIndex, const ByteArray& data_8X, 
        ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_ECB_EncMode;
        size_t ivlen = 8;
        byte iv[8] = { 0 };

        ASSERT_FuncErrRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, ByteArray(iv, ivlen),
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥SM4 ECB加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] wkIndex 加密数据的工作密钥索引
     * @param [in] data_16X 待加密的数据
     * @param [out] buff_16X 加密后的数据
     */
    bool WK_SM4_ECB_Encrypt(byte mkIndex, byte wkIndex, const ByteArray& data_16X, 
        ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_ECB_EncMode;
        size_t ivlen = 16;
        byte iv[16] = { 0 };

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, ByteArray(iv, ivlen),
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥DES CBC加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] wkIndex 加密数据的工作密钥索引
     * @param [in] iv_8 向量
     * @param [in] data_8X 待加密的数据
     * @param [out] buff_8X 加密后的数据
     */
    bool WK_DES_CBC_Encrypt(byte mkIndex, byte wkIndex, const ByteArray& iv_8, 
        const ByteArray& data_8X, ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_CBC_EncMode;
        size_t ivlen = 8;

        ASSERT_FuncErrInfoRet(iv_8.GetLength() >= ivlen, DeviceError::ArgLengthErr,
            "IV长度错误");
        ASSERT_FuncErrInfoRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr, "待加密数据长度错误");

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, iv_8,
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥SM4 CBC加密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 加密数据的主密钥索引
     * @param [in] wkIndex 加密数据的工作密钥索引
     * @param [in] iv_16 向量
     * @param [in] data_16X 待加密的数据
     * @param [out] buff_16X 加密后的数据
     */
    bool WK_SM4_CBC_Encrypt(byte mkIndex, byte wkIndex, const ByteArray& iv_16, 
        const ByteArray& data_16X, ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_CBC_EncMode;
        size_t ivlen = 16;

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, iv_16,
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "加密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
    /**
     * @brief 工作密钥DES ECB解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] wkIndex 解密数据的工作密钥索引
     * @param [in] data_8X 待解密的数据
     * @param [out] buff_8X 解密后的数据
     */
    bool WK_DES_ECB_Decrypt(byte mkIndex, byte wkIndex, const ByteArray& data_8X, 
        ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_ECB_DecMode;
        size_t ivlen = 8;
        byte iv[8] = { 0 };

        ASSERT_FuncErrRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, ByteArray(iv, ivlen),
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥SM4 ECB解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] data_16X 待解密的数据
     * @param [out] buff_16X 解密后的数据
     */
    bool WK_SM4_ECB_Decrypt(byte mkIndex, byte wkIndex, const ByteArray& data_16X, 
        ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_ECB_DecMode;
        size_t ivlen = 16;
        byte iv[16] = { 0 };

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, ByteArray(iv, ivlen),
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥DES CBC解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] wkIndex 解密数据的工作密钥索引
     * @param [in] iv_8 向量
     * @param [in] data_8X 待解密的数据
     * @param [out] buff_8X 解密后的数据
     */
    bool WK_DES_CBC_Decrypt(byte mkIndex, byte wkIndex, const ByteArray& iv_8, const ByteArray& data_8X, 
        ByteBuilder& buff_8X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = DES_CBC_DecMode;
        size_t ivlen = 8;

        ASSERT_FuncErrInfoRet(iv_8.GetLength() >= ivlen, DeviceError::ArgLengthErr,
            "IV长度错误");
        ASSERT_FuncErrInfoRet((data_8X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr, "待解密数据长度错误");

        for(size_t i = 0;i < data_8X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, iv_8,
                data_8X.SubArray(i, ivlen), buff_8X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    /**
     * @brief 工作密钥SM4 CBC解密数据
     * @date 2016-11-17 15:13
     * 
     * @param [in] mkIndex 解密数据的主密钥索引
     * @param [in] wkIndex 解密数据的工作密钥索引
     * @param [in] iv_16 向量
     * @param [in] data_16X 待解密的数据
     * @param [out] buff_16X 解密后的数据
     */
    bool WK_SM4_CBC_Decrypt(byte mkIndex, byte wkIndex, const ByteArray& iv_16, const ByteArray& data_16X, 
        ByteBuilder& buff_16X)
    {
        LOG_FUNC_NAME();
        CryptMode mode = SM4_CBC_DecMode;
        size_t ivlen = 16;

        ASSERT_FuncErrRet((data_16X.GetLength() % ivlen) == 0,
            DeviceError::ArgLengthErr);

        for(size_t i = 0;i < data_16X.GetLength(); i += ivlen)
        {
            if(!_WKeyCrypt(mkIndex, wkIndex, mode, iv_16,
                data_16X.SubArray(i, ivlen), buff_16X))
            {
                _logErr(DeviceError::OperatorErr, "解密数据失败");
                return _logRetValue(false);
            }
        }
        return _logRetValue(true);
    }
    //----------------------------------------------------- 
};
//--------------------------------------------------------- 
} // namespace pinpad
} // namespace application 
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_H002PINPADDEVADAPTER_H_
//========================================================= 